﻿using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Xml.Serialization;

namespace ConfExpert
{
    public partial class CellStyler : DevExpress.XtraEditors.XtraUserControl
    {
        CellStyle cellStyle = new CellStyle();

        public CellStyler()
        {
            InitializeComponent();
        }

        public CellStyle Style
        {
            get
            {
                return cellStyle;
            }
            set
            {
                cellStyle = value;
            }
        }

        private void CellStyler_Load(object sender, EventArgs e)
        {
            InitControls();
        }

        private void InitControls()
        {
            ControlsRefreshing = true;
            DevExpress.XtraEditors.Repository.RepositoryItemComboBox cmbFontSize = (DevExpress.XtraEditors.Repository.RepositoryItemComboBox)(bbiFontSize.Edit);

            cmbFontSize.Items.Add(8.25f);
            cmbFontSize.Items.Add(9f);
            cmbFontSize.Items.Add(10f);
            cmbFontSize.Items.Add(12f);
            cmbFontSize.Items.Add(14f);
            cmbFontSize.Items.Add(16f);
            cmbFontSize.Items.Add(20f);
            bbiFontSize.EditValue = 8.25f;

            bbiForeColor.EditValue = Color.Black;
            bbiBackColor.EditValue = Color.White;

            bbiFont.EditValue = "Tahoma";
            bbiBold.Checked = false;

            ControlsRefreshing = false;
        }

        private string keyColumn;
        public string KeyColumn
        {
            get { return keyColumn; }
            set { keyColumn = value; }
        }

        private GridView gridView;
        public GridView GridView
        {
            get { return gridView; }
            set { gridView = value; }
        }

        public CellStyle.Cell GetCell(string RowKey, string ColumnName, bool CreateIfNotExists)
        {
            CellStyle.Row row = Style.GetRow(RowKey);
            if (row == null)
            {
                if (!CreateIfNotExists)
                {
                    return null;
                }
                else
                {
                    row = new CellStyle.Row();
                    row.RowKey = RowKey;

                    CellStyle.Cell cell = new CellStyle.Cell();
                    cell.ColumnName = ColumnName;

                    row.AddCell(cell, row);
                    Style.Rows.Add(row);

                    return cell;
                }
            }
            else
            {
                CellStyle.Cell cell = row.GetCell(ColumnName);
                if (cell == null)
                {
                    if (!CreateIfNotExists)
                    {
                        return null;
                    }
                    else
                    {
                        CellStyle.Cell newCell = new CellStyle.Cell();
                        newCell.ColumnName = ColumnName;
                        row.AddCell(newCell, row);
                        return newCell;
                    }
                }
                else
                {
                    return cell;
                }
            }
        }

        public void BindToGridView(GridView GridView, string KeyColumn)
        {
            this.GridView = GridView;
            this.KeyColumn = KeyColumn;

            GridView.RowCellStyle += new RowCellStyleEventHandler(GridView_RowCellStyle);
            GridView.FocusedColumnChanged += new DevExpress.XtraGrid.Views.Base.FocusedColumnChangedEventHandler(GridView_FocusedColumnChanged);
            GridView.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(GridView_FocusedRowChanged);
        }
        public void BindToGridView(GridView GridView, string KeyColumn, string SavedStyle)
        {
            if (SavedStyle.Trim() == string.Empty || SavedStyle == null)
            {
                BindToGridView(GridView, KeyColumn);
                return;
            }

           


            this.Style = CellStyle.Get(SavedStyle);

            foreach (ConfExpert.CellStyle.Row row in this.Style.Rows)
            {
                foreach (ConfExpert.CellStyle.Cell cell in row.Cells)
                {
                    cell.ParentRow = row;
                }
            }

            this.GridView = GridView;
            this.KeyColumn = KeyColumn;

            GridView.RowCellStyle += new RowCellStyleEventHandler(GridView_RowCellStyle);
            GridView.FocusedColumnChanged += new DevExpress.XtraGrid.Views.Base.FocusedColumnChangedEventHandler(GridView_FocusedColumnChanged);
            GridView.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(GridView_FocusedRowChanged);
        }

        void GridView_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            SyncControls();
        }

        void GridView_FocusedColumnChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedColumnChangedEventArgs e)
        {
            SyncControls();
        }


        #region GridViewEvents


        void GridView_RowCellStyle(object sender, RowCellStyleEventArgs e)
        {
            if (e.RowHandle < 0)
                return;

            string rowKey = GridView.GetRowCellValue(e.RowHandle, GridView.Columns.ColumnByFieldName(KeyColumn)).ToString();
            CellStyle.Cell c = GetCell(rowKey, e.Column.FieldName, false);


            if (c != null)
            {
                if (!GridView.IsCellSelected(e.RowHandle, e.Column))
                {
                    e.Appearance.BackColor = c.GetBackColor();
                }
                e.Appearance.ForeColor = c.GetForeColor();

                if (c.Bold)
                {
                    e.Appearance.Font = new Font(c.FontName, c.FontSize, FontStyle.Bold);
                }
                else
                {
                    e.Appearance.Font = new Font(c.FontName, c.FontSize);
                }
            }
        }

        #endregion

        #region Control Events

        void control_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            GridCell[] selectedCells = GridView.GetSelectedCells();

            foreach (GridCell gc in selectedCells)
            {
                string rowKey = GridView.GetRowCellValue(gc.RowHandle, KeyColumn).ToString();
                CellStyle.Cell cell = GetCell(rowKey, gc.Column.FieldName, true);


                if (!ControlsRefreshing)
                {
                    if (e.Item.Name == bbiBackColor.Name)
                        cell.BackColor = ((Color)bbiBackColor.EditValue).Name;
                    else if (e.Item.Name == bbiForeColor.Name)
                        cell.ForeColor = ((Color)bbiForeColor.EditValue).Name;
                    else if (e.Item.Name == bbiBold.Name)
                        cell.Bold = bbiBold.Checked;
                    else if (e.Item.Name == bbiFont.Name)
                        cell.FontName = bbiFont.EditValue.ToString();
                    else if (e.Item.Name == bbiFontSize.Name)
                        cell.FontSize = (float)bbiFontSize.EditValue;
                    else if (e.Item.Name == bbiClear.Name)
                        cell.ParentRow.Cells.Remove(cell);
                }
            }
        }

        #endregion

        #region SyncControls
        bool ControlsRefreshing = false;
        public void SyncControls()
        {
            if (GridView.FocusedRowHandle >= 0)
            {
                ControlsRefreshing = true;

                string rowKey = GridView.GetRowCellValue(GridView.FocusedRowHandle, GridView.Columns.ColumnByFieldName(KeyColumn)).ToString();
                CellStyle.Cell cell = GetCell(rowKey, GridView.FocusedColumn.FieldName, false);


                if (cell != null)
                {
                    bbiFont.EditValue = cell.FontName;
                    bbiFontSize.EditValue = cell.FontSize;

                    //bbiBackColor.EditValue = cell.GetBackColor();
                    //bbiForeColor.EditValue = cell.GetForeColor();
                    bbiBold.Checked = cell.Bold;
                }
                else
                {

                    bbiFontSize.EditValue = 8.25f;
                    //bbiBackColor.EditValue = Color.White;
                    //bbiForeColor.EditValue = Color.Black;
                    bbiFont.EditValue = "Tahoma";
                    bbiBold.Checked = false;
                }

                ControlsRefreshing = false;
            }
        }
        #endregion
    }

    public class CellStyle
    {
        public List<Row> Rows = new List<Row>();

        public Row GetRow(string RowKey)
        {
            foreach (Row row in Rows)
            {
                if (row.RowKey == RowKey)
                {
                    return row;
                }
            }
            return null;
        }

        public override string ToString()
        {
            Cell defaultCell = new Cell();

            List<Cell> cellToDelete = new List<Cell>();

            foreach (Row row in this.Rows)
            {
                foreach (Cell cell in row.Cells)
                {
                    if (cell.BackColor == defaultCell.BackColor
                        && cell.Bold == defaultCell.Bold
                        && cell.ForeColor == defaultCell.ForeColor
                        && cell.FontName == defaultCell.FontName
                        && cell.FontSize == defaultCell.FontSize
                        )
                    {
                        cell.ParentRow = row;
                        cellToDelete.Add(cell);
                    }
                }
            }

            foreach (Cell cell in cellToDelete)
            {
                cell.ParentRow.Cells.Remove(cell);
            }

            List<Row> rowsToDelete = new List<Row>();
            foreach (Row row in this.Rows)
            {
                if (row.Cells.Count == 0)
                {
                    rowsToDelete.Add(row);
                }
            }

            foreach (Row row in rowsToDelete)
            {
                Rows.Remove(row);
            }


            System.IO.StringWriter s = new System.IO.StringWriter();
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(this.GetType());
            serializer.Serialize(s, this);
            return s.ToString();
        }

        public static CellStyle Get(string xml)
        {
            if (xml != string.Empty)
            {
                StringReader sr = new StringReader(xml);
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(CellStyle));
                return (CellStyle)serializer.Deserialize(sr);
            }
            else
                return null;
        }

        #region Cell
        public class Cell
        {
            private string columnName;

            public string ColumnName
            {
                get { return columnName; }
                set { columnName = value; }
            }
            private string fontName = "Tahoma";
            public string FontName
            {
                get { return fontName; }
                set { fontName = value; }
            }

            string foreColor = Color.Black.Name;
            public string ForeColor
            {
                get { return foreColor; }
                set { foreColor = value; }
            }

            string backColor = Color.White.Name;
            public string BackColor
            {
                get { return backColor; }
                set { backColor = value; }
            }

            private float fontSize = 8.25f;
            public float FontSize
            {
                get { return fontSize; }
                set { fontSize = value; }
            }

            private bool bold = false;
            public bool Bold
            {
                get { return bold; }
                set { bold = value; }
            }

            public Color GetForeColor()
            {
                return Color.FromName(ForeColor);
            }
            public Color GetBackColor()
            {
                return Color.FromName(BackColor);
            }


            private Row parentRow;

            [XmlIgnore]
            public Row ParentRow
            {
                get { return parentRow; }
                set { parentRow = value; }
            }




        }
        #endregion

        #region Row
        public class Row
        {
            string rowKey;
            public string RowKey
            {
                get { return rowKey; }
                set { rowKey = value; }
            }

            private List<Cell> cells = new List<Cell>();
            public List<Cell> Cells
            {
                get { return cells; }
                set { cells = value; }
            }

            public void AddCell(Cell cell, Row ParentRow)
            {
                cell.ParentRow = ParentRow;
                cells.Add(cell);
            }


            public Cell GetCell(string ColumnName)
            {
                foreach (Cell cell in Cells)
                {
                    if (cell.ColumnName == ColumnName)
                    {
                        return cell;
                    }
                }
                return null;
            }
        }
        #endregion
    }
}